package fr.insalyon.sims.broadcast.image;

import java.util.ArrayList;
import java.util.List;

public class RawImage {
	// ------------------------------------------------------- CONSTANTS -- //
	// ------------------------------------------------------ ATTRIBUTES -- //
	
	private List<Integer> missingData;
	
	private byte[] data;
	
	private int bytesReceived;
	
	// ---------------------------------------------------- CONSTRUCTORS -- //
	
	public RawImage(int size) {
		data = new byte[size];
		missingData = new ArrayList<Integer>();
		missingData.add(0);
		missingData.add(size);
	}
	
	// --------------------------------------------------------- METHODS -- //
	
	public synchronized void addFragment(byte[] fragment, int srcOffset,
			int srcLength, int dstOffset) {
		System.arraycopy(fragment, srcOffset, data, dstOffset, srcLength);
		bytesReceived += srcLength;
		
		for (int i = 0; i < missingData.size(); i++) {
			if (missingData.get(i) == dstOffset) {
				// Fragment suivant un fragment déjà reçu, ou premier fragment
				missingData.set(i, dstOffset + srcLength);
				
				if (missingData.get(i).equals(missingData.get(i + 1))) {
					// La fin du fragment avec le début d'un fragment déjà reçu
					missingData.remove(i);
					missingData.remove(i);
				}
				break;
			} else if (dstOffset < missingData.get(i)) {
				if (missingData.get(i) == dstOffset + srcLength) {
					// Fragment dont la fin coincide avec le début d'un
					// fragment déjà reçu
					missingData.set(i, dstOffset);
				} else {
					// Fragment précédé et suivi de fragments pas encore reçus
					missingData.add(i, dstOffset);
					missingData.add(i + 1, dstOffset + srcLength);
				}
				break;
			}
		}
	}
	
	public boolean isComplete() {
		return missingData.size() == 0;
	}
	
	public List<Integer> getMissingDataLocation() {
		return missingData;
	}
	
	public byte[] getData() {
		return data;
	}
	
	public int getBytesReceived() {
		return bytesReceived;
	}
	
	// ------------------------------------------------- PRIVATE METHODS -- //
	// --------------------------------------------------- INNER CLASSES -- //
}
